#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "x86_registers.h"


const struct x86_register i386_registers[] =
{
  { "st", FloatReg|FloatAcc, 0, 0 },
  { "al", Reg8|Acc, 0, 0 },
  { "cl", Reg8|ShiftCount, 0, 1 },
  { "dl", Reg8, 0, 2 },
  { "bl", Reg8, 0, 3 },
  { "ah", Reg8, 0, 4 },
  { "ch", Reg8, 0, 5 },
  { "dh", Reg8, 0, 6 },
  { "bh", Reg8, 0, 7 },
  { "axl", Reg8|Acc, RegRex64, 0 },
  { "cxl", Reg8, RegRex64, 1 },
  { "dxl", Reg8, RegRex64, 2 },
  { "bxl", Reg8, RegRex64, 3 },
  { "spl", Reg8, RegRex64, 4 },
  { "bpl", Reg8, RegRex64, 5 },
  { "sil", Reg8, RegRex64, 6 },
  { "dil", Reg8, RegRex64, 7 },
  { "r8b", Reg8, RegRex|RegRex64, 0 },
  { "r9b", Reg8, RegRex|RegRex64, 1 },
  { "r10b", Reg8, RegRex|RegRex64, 2 },
  { "r11b", Reg8, RegRex|RegRex64, 3 },
  { "r12b", Reg8, RegRex|RegRex64, 4 },
  { "r13b", Reg8, RegRex|RegRex64, 5 },
  { "r14b", Reg8, RegRex|RegRex64, 6 },
  { "r15b", Reg8, RegRex|RegRex64, 7 },
  { "ax", Reg16|Acc, 0, 0 },
  { "cx", Reg16, 0, 1 },
  { "dx", Reg16|InOutPortReg, 0, 2 },
  { "bx", Reg16|BaseIndex, 0, 3 },
  { "sp", Reg16, 0, 4 },
  { "bp", Reg16|BaseIndex, 0, 5 },
  { "si", Reg16|BaseIndex, 0, 6 },
  { "di", Reg16|BaseIndex, 0, 7 },
  { "r8w", Reg16, RegRex, 0 },
  { "r9w", Reg16, RegRex, 1 },
  { "r10w", Reg16, RegRex, 2 },
  { "r11w", Reg16, RegRex, 3 },
  { "r12w", Reg16, RegRex, 4 },
  { "r13w", Reg16, RegRex, 5 },
  { "r14w", Reg16, RegRex, 6 },
  { "r15w", Reg16, RegRex, 7 },
  { "eax", Reg32|BaseIndex|Acc, 0, 0 },
  { "ecx", Reg32|BaseIndex, 0, 1 },
  { "edx", Reg32|BaseIndex, 0, 2 },
  { "ebx", Reg32|BaseIndex, 0, 3 },
  { "esp", Reg32, 0, 4 },
  { "ebp", Reg32|BaseIndex, 0, 5 },
  { "esi", Reg32|BaseIndex, 0, 6 },
  { "edi", Reg32|BaseIndex, 0, 7 },
  { "r8d", Reg32|BaseIndex, RegRex, 0 },
  { "r9d", Reg32|BaseIndex, RegRex, 1 },
  { "r10d", Reg32|BaseIndex, RegRex, 2 },
  { "r11d", Reg32|BaseIndex, RegRex, 3 },
  { "r12d", Reg32|BaseIndex, RegRex, 4 },
  { "r13d", Reg32|BaseIndex, RegRex, 5 },
  { "r14d", Reg32|BaseIndex, RegRex, 6 },
  { "r15d", Reg32|BaseIndex, RegRex, 7 },
  { "rax", Reg64|BaseIndex|Acc, 0, 0 },
  { "rcx", Reg64|BaseIndex, 0, 1 },
  { "rdx", Reg64|BaseIndex, 0, 2 },
  { "rbx", Reg64|BaseIndex, 0, 3 },
  { "rsp", Reg64, 0, 4 },
  { "rbp", Reg64|BaseIndex, 0, 5 },
  { "rsi", Reg64|BaseIndex, 0, 6 },
  { "rdi", Reg64|BaseIndex, 0, 7 },
  { "r8", Reg64|BaseIndex, RegRex, 0 },
  { "r9", Reg64|BaseIndex, RegRex, 1 },
  { "r10", Reg64|BaseIndex, RegRex, 2 },
  { "r11", Reg64|BaseIndex, RegRex, 3 },
  { "r12", Reg64|BaseIndex, RegRex, 4 },
  { "r13", Reg64|BaseIndex, RegRex, 5 },
  { "r14", Reg64|BaseIndex, RegRex, 6 },
  { "r15", Reg64|BaseIndex, RegRex, 7 },
  { "es", SReg2, 0, 0 },
  { "cs", SReg2, 0, 1 },
  { "ss", SReg2, 0, 2 },
  { "ds", SReg2, 0, 3 },
  { "fs", SReg3, 0, 4 },
  { "gs", SReg3, 0, 5 },
  { "cr0", Control, 0, 0 },
  { "cr1", Control, 0, 1 },
  { "cr2", Control, 0, 2 },
  { "cr3", Control, 0, 3 },
  { "cr4", Control, 0, 4 },
  { "cr5", Control, 0, 5 },
  { "cr6", Control, 0, 6 },
  { "cr7", Control, 0, 7 },
  { "cr8", Control, RegRex, 0 },
  { "cr9", Control, RegRex, 1 },
  { "cr10", Control, RegRex, 2 },
  { "cr11", Control, RegRex, 3 },
  { "cr12", Control, RegRex, 4 },
  { "cr13", Control, RegRex, 5 },
  { "cr14", Control, RegRex, 6 },
  { "cr15", Control, RegRex, 7 },
  { "db0", Debug, 0, 0 },
  { "db1", Debug, 0, 1 },
  { "db2", Debug, 0, 2 },
  { "db3", Debug, 0, 3 },
  { "db4", Debug, 0, 4 },
  { "db5", Debug, 0, 5 },
  { "db6", Debug, 0, 6 },
  { "db7", Debug, 0, 7 },
  { "db8", Debug, RegRex, 0 },
  { "db9", Debug, RegRex, 1 },
  { "db10", Debug, RegRex, 2 },
  { "db11", Debug, RegRex, 3 },
  { "db12", Debug, RegRex, 4 },
  { "db13", Debug, RegRex, 5 },
  { "db14", Debug, RegRex, 6 },
  { "db15", Debug, RegRex, 7 },
  { "dr0", Debug, 0, 0 },
  { "dr1", Debug, 0, 1 },
  { "dr2", Debug, 0, 2 },
  { "dr3", Debug, 0, 3 },
  { "dr4", Debug, 0, 4 },
  { "dr5", Debug, 0, 5 },
  { "dr6", Debug, 0, 6 },
  { "dr7", Debug, 0, 7 },
  { "dr8", Debug, RegRex, 0 },
  { "dr9", Debug, RegRex, 1 },
  { "dr10", Debug, RegRex, 2 },
  { "dr11", Debug, RegRex, 3 },
  { "dr12", Debug, RegRex, 4 },
  { "dr13", Debug, RegRex, 5 },
  { "dr14", Debug, RegRex, 6 },
  { "dr15", Debug, RegRex, 7 },
  { "tr0", Test, 0, 0 },
  { "tr1", Test, 0, 1 },
  { "tr2", Test, 0, 2 },
  { "tr3", Test, 0, 3 },
  { "tr4", Test, 0, 4 },
  { "tr5", Test, 0, 5 },
  { "tr6", Test, 0, 6 },
  { "tr7", Test, 0, 7 },
  { "mm0", RegMMX, 0, 0 },
  { "mm1", RegMMX, 0, 1 },
  { "mm2", RegMMX, 0, 2 },
  { "mm3", RegMMX, 0, 3 },
  { "mm4", RegMMX, 0, 4 },
  { "mm5", RegMMX, 0, 5 },
  { "mm6", RegMMX, 0, 6 },
  { "mm7", RegMMX, 0, 7 },
  { "xmm0", RegXMM, 0, 0 },
  { "xmm1", RegXMM, 0, 1 },
  { "xmm2", RegXMM, 0, 2 },
  { "xmm3", RegXMM, 0, 3 },
  { "xmm4", RegXMM, 0, 4 },
  { "xmm5", RegXMM, 0, 5 },
  { "xmm6", RegXMM, 0, 6 },
  { "xmm7", RegXMM, 0, 7 },
  { "xmm8", RegXMM, RegRex, 0 },
  { "xmm9", RegXMM, RegRex, 1 },
  { "xmm10", RegXMM, RegRex, 2 },
  { "xmm11", RegXMM, RegRex, 3 },
  { "xmm12", RegXMM, RegRex, 4 },
  { "xmm13", RegXMM, RegRex, 5 },
  { "xmm14", RegXMM, RegRex, 6 },
  { "xmm15", RegXMM, RegRex, 7 },
  { "rip", BaseIndex, 0, 0 },
  { "st(0)", FloatReg|FloatAcc, 0, 0 },
  { "st(1)", FloatReg, 0, 1 },
  { "st(2)", FloatReg, 0, 2 },
  { "st(3)", FloatReg, 0, 3 },
  { "st(4)", FloatReg, 0, 4 },
  { "st(5)", FloatReg, 0, 5 },
  { "st(6)", FloatReg, 0, 6 },
  { "st(7)", FloatReg, 0, 7 },
};


static void inline
str_tolower(char * str)
{
	char * p = str;
	while (*p != '\0') {
		*p = isupper(*p) ? tolower(*p) : *p;
		p++;
	}
}


static void inline
str_toupper(char * str)
{
	char * p = str;
	while (*p != '\0') {
		*p = islower(*p) ? toupper(*p) : *p;
		p++;
	}
}


struct x86_register
find_register(const char * _name)
{
	char * name = strdupa(_name);
	str_tolower(name);

	for (int i = 0;
			i < (sizeof(i386_registers) / sizeof(i386_registers[0]));
			i++)
	{
		if (strcmp(i386_registers[i].reg_name, name) == 0)
			return i386_registers[i];
	}
	printf("unknown register: %s\n", _name);
	exit(-1);
}

// vim:ts=4:sw=4

